package daiia;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.StringTokenizer;


import com.myprofile.profile.ProfileType;


import recommender.Cluster;
import recommender.ClusterArray;
import recommender.IUserProfileDelegate_Stub;
import recommender.ProfileStatement;
import recommender.RecommendationItemUI;
import recommender.SmartMuseumSearch_Impl;
import recommender.UserProfile;

public class RecommenderService {
	
	static final String sm_schema="http://www.smartmuseum.eu/ns/annotation#";
	static final String VisitType = "http://www.yso.fi/onto/user-profile/visitor-type/";
	static final String Motivation = "http://www.yso.fi/onto/user-profile/motivation-of-visit/";
	static final String	TargetGroup = "http://www.yso.fi/onto/user-profile/target-group/";
	static final String Abilities = "http://www.yso.fi/onto/user-profile/abilities/"; 
	static final String	Language = "http://www.yso.fi/onto/user-profile/language/";
	static final String Profile_Schema = "http://www.smartmuseum.eu/ns/profile#";
	static final String Context_Schema =  "http://www.smartmuseum.eu/ns/context#";
	static final String AAT= "http://e-culture.multimedian.nl/ns/getty/aat#";
	
	HashMap<String, String> mapAATName_Id = new HashMap<String, String> ();
	String strFileName = "data/ItemID.txt";
	
	public RecommenderService () {
		loadAAT_Dataset();
	}
	
	private void loadAAT_Dataset () {
	
		
		try {
			BufferedReader inputBuf =  new BufferedReader(new FileReader(strFileName));
			String strline;
			
			while( (strline = inputBuf.readLine()) != null) {				
				StringTokenizer tokenizer = new StringTokenizer(strline, ",", false);
				while (tokenizer.hasMoreElements()) {			
					String id = tokenizer.nextToken().toLowerCase().trim(); // skip the number
					String name = tokenizer.nextToken().toLowerCase().trim();
					mapAATName_Id.put(name, id);
				}
			}
			inputBuf.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	 
		
	}
	
 private static void print_recommendation_results(ClusterArray recommendationResults) {
		
		Cluster[] result_clusters = recommendationResults.getItem();
		System.out.print("\n\n--- Recommended Items ---\n");
		for (int i = 0; i < result_clusters.length; i++) {
			System.out.println("Cluster Name: " + result_clusters[i].getClusterName());
			RecommendationItemUI[] recommendationItems = result_clusters[i].getRecommendationItems();
			
			for (int j = 0; j < recommendationItems.length; j++) {
					System.out.print("URI: " + recommendationItems[j].getUri());
					System.out.print("  Name: " + recommendationItems[j].getName());
					System.out.println("  Score: " + recommendationItems[j].getScore());				
			}
		}
		
	}

	public static void print_profile_statements (UserProfile userProfile){
		ProfileStatement[] listPS = userProfile.getProfileStatements();
		System.out.print("\n\n--- Profile Statements ---\n");
		if (listPS != null)
		for (int i = 0; i < listPS.length; i++) {
			System.out.print("Subject: " + listPS[i].getSubject());
			System.out.print(", Predicate: " + listPS[i].getPredicate());
			System.out.print(", Object: " + listPS[i].getObject());
			System.out.println(", Weight: " + listPS[i].getWeight());		
		}
	}
	
	public static void print_context_statements (UserProfile userProfile){
		
		ProfileStatement[] listCS = userProfile.getContextStatements();
		System.out.print("\n\n--- Context Statements ---\n");
		if (listCS != null){
			for (int i = 0; i < listCS.length; i++) {
			System.out.print("Subject: " + listCS[i].getSubject());
			System.out.print(", Predicate: " + listCS[i].getPredicate());
			System.out.print(", Object: " + listCS[i].getObject());
			System.out.println(", Weight: " + listCS[i].getWeight());	
			}
		}
	}
	/**
	 * Invoke recommendation service 
	 * @param profile : user profile in Recommendation format
	 * @return : a cluster of recommended items
	 */
	public ClusterArray getRecommendation(ProfileType profile) {
		SmartMuseumSearch_Impl impl = new SmartMuseumSearch_Impl();
		IUserProfileDelegate_Stub userProfileDelegate = (IUserProfileDelegate_Stub) impl.getSmartMuseumSearch();
		UserProfile userProfile = new UserProfile();
		// --- Modified user profile and using it for recommendation
		
		userProfile = initializeUserProfile(profile);
		print_profile_statements(userProfile);
		print_context_statements(userProfile);
		ClusterArray recommendation_results;
		try {
			recommendation_results = userProfileDelegate.getRecommendationsUserProfile(userProfile, "1", "1", "1", "1");
			return recommendation_results;
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		
		return null;
	}
	
	/**
	 * Initialize recommendation compliance profile from smart user profile
	 * @param sm_profile : smart musuem user profile
	 * @return : initialized profile according to recommendation service 
	 */
	public UserProfile initializeUserProfile (ProfileType sm_profile) {
		UserProfile userProfile = new UserProfile();
		
		ProfileStatement[] arrPS1 = creatVisitedItems_ProfileStatement (sm_profile);
		ProfileStatement[] arrPS2 = creatInterests_ProfileStatement (sm_profile);
		ProfileStatement[] arrPS3 = creatBasicUserInfo_ProfileStatement (sm_profile);
		
		ProfileStatement[] arrPS_All = new ProfileStatement[arrPS1.length + arrPS2.length + arrPS3.length];
		int k = 0;
		for (int i = 0; i < arrPS1.length; i++ , k++)
			arrPS_All[k] =  arrPS1[i];
		
		for (int i = 0; i < arrPS2.length; i++ , k++)
			arrPS_All[k] =  arrPS2[i];
		
		for (int i = 0; i < arrPS3.length; i++ , k++)
			arrPS_All[k] =  arrPS3[i];
		
		userProfile.setProfileStatements(arrPS_All);
		userProfile.setContextStatements(null);
		
		return userProfile;
	}

	/**
	 * Create Profile Statements from visited items
	 * @param sm_profile
	 * @return
	 */
	private ProfileStatement[] creatVisitedItems_ProfileStatement(ProfileType sm_profile) {
		ProfileStatement[] arrPS = new ProfileStatement[sm_profile.getVisitedItems().getVisitedItem().size()] ;
		
		for (int i = 0; i < sm_profile.getVisitedItems().getVisitedItem().size(); i++) {
			arrPS[i] = new ProfileStatement();
			arrPS[i].setSubject(null);
			arrPS[i].setPredicate("http://smartmuseum.eu/ns/schema.rdf#objectType");
			String key = sm_profile.getVisitedItems().getVisitedItem().get(i).getObjectType().toLowerCase();
			arrPS[i].setObject(mapAATName_Id.get(key));
		}
		
		return arrPS;
	}

	
	/**
	 * Create Profile Statements from user interests
	 * @param sm_profile
	 * @return
	 */
	private ProfileStatement[] creatInterests_ProfileStatement(ProfileType sm_profile) {
		ProfileStatement[] arrPS = new ProfileStatement[sm_profile.getInterests().getInterest().size()] ;
		
		for (int i = 0; i < sm_profile.getInterests().getInterest().size(); i++) {
			arrPS[i] = new ProfileStatement();
			arrPS[i].setSubject(null);
			arrPS[i].setPredicate(Profile_Schema + "interestSubject");
			arrPS[i].setObject(sm_profile.getInterests().getInterest().get(i));
		}
		
		return arrPS;
	}
	
	/**
	 * Create Profile Statements from basic user information 
	 * @param sm_profile : Smart Musuem User profile
	 * @return
	 */
	private ProfileStatement[] creatBasicUserInfo_ProfileStatement(ProfileType sm_profile) {
		ProfileStatement[] arrPS = new ProfileStatement[4] ;
		
		//Set Age Group
		arrPS[0] = new ProfileStatement();
		arrPS[0].setSubject(null);	
		arrPS[0].setPredicate(sm_schema + "ageGroup");
		if (sm_profile.getAge() < 35) // adults
			arrPS[0].setObject("http://e-culture.multimedian.nl/ns/getty/aat#300154397");
		else	//elderly
			arrPS[0].setObject("http://e-culture.multimedian.nl/ns/getty/aat#300025913");
		arrPS[0].setWeight(1);
		arrPS[0].setMust(false);

		// Set Education
		arrPS[1] = new ProfileStatement();
		arrPS[1].setSubject(null);
		arrPS[1].setPredicate(sm_schema + "education");
		if (sm_profile.getEducation().equalsIgnoreCase("higher education"))
			arrPS[1].setObject("http://e-culture.multimedian.nl/ns/getty/aat#300054370");
		else if (sm_profile.getEducation().equalsIgnoreCase("postsecondary education"))
			arrPS[1].setObject("http://e-culture.multimedian.nl/ns/getty/aat#300254154");
		else if (sm_profile.getEducation().equalsIgnoreCase("elementary education"))
			arrPS[1].setObject("http://e-culture.multimedian.nl/ns/getty/aat#300054367");
		else if (sm_profile.getEducation().equalsIgnoreCase("secondary education"))
			arrPS[1].setObject("http://e-culture.multimedian.nl/ns/getty/aat#300054368");
		else
			System.out.println("Error : Undefiend Education Level: " + sm_profile.getEducation());
		
		// Set Attitude
		arrPS[2] = new ProfileStatement();
		arrPS[2].setSubject(null);
		arrPS[2].setPredicate(sm_schema + "visitorType");
		arrPS[2].setObject(Profile_Schema +  sm_profile.getAttitude());
		
		// Set Motivation of Visit
		arrPS[3] = new ProfileStatement();
		arrPS[3].setSubject(null);
		arrPS[3].setPredicate(sm_schema + "MotivationOfVisit");
		arrPS[3].setObject(Profile_Schema + sm_profile.getMotivationOfVisit());
		
		return arrPS;
	}
	
	
	/**
	 * The following sample code shows how you can send profile to Recommendation service and get recommendation back
	 * and then store the received museum items in a another XML profile 
	 * @param args
	 */
	
	
	public static void main(String[] args) {
		RecommenderService service = new RecommenderService();
		ProfileManager managerProfile = new ProfileManager();
		ProfileType profileStep1 = managerProfile.createProfile();
		ClusterArray recommendation_results = service.getRecommendation(profileStep1);
		// Print recommended items
		print_recommendation_results(recommendation_results);
		managerProfile.dumpProfileStep2(profileStep1, recommendation_results, "profileStep2.xml");
	}
}
